home *** CD-ROM | disk | FTP | other *** search
- #ifdef OSK
- /* OS- and machine-dependent stuff for asynch ports on OS-9
- * Copyright 1993 Brian A. Lantz, KO4KS
- */
- #include "global.h"
- #include <dos.h>
- #include "mbuf.h"
- #include "proc.h"
- #include "iface.h"
- #include "n8250.h"
- #include "asy.h"
- #include "devparam.h"
- #include "pc.h"
- #include <sgstat.h>
- #include <modes.h>
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: osk_asy.c,v 1.9 1996/12/23 22:44:37 root Exp root $";
- #endif
-
- extern int _gs_opt();
- extern void _ss_opt();
-
- #define ASY_MAX 5
- #define PARAM_SPEED 10
-
- static void asy_tx (int dev,void *p1,void *p2);
-
- struct asy Asy[ASY_MAX];
-
- /* Initialize asynch port "dev" */
- int
- asy_init(dev,ifp,arg1,arg2,bufsize,trigchar,monitor,speed,force,triglevel)
- int dev;
- struct iface *ifp;
- char *arg1,*arg2; /* Attach args for address and vector */
- int16 bufsize;
- int trigchar;
- char monitor;
- long speed;
- int force;
- int triglevel;
- {
- register unsigned base;
- register struct fifo *fp;
- register struct asy *ap;
- char termname[8], prefix[4];
- char *ifn;
- struct sgbuf sbuf;
- short *nm = (short *) prefix;
-
- ap = &Asy[dev];
- ap->iface = ifp;
-
- ap->addr = atoi(arg2); /* hex string for device name prefix */
- *nm = htoi(arg1); /* hex-coded ASCII for name prefix "t" etc */
- if (!prefix[0])
- prefix[0] = 't';
-
- /* Set up receiver FIFO */
- fp = &ap->fifo;
- fp->buf = mallocw(bufsize);
- fp->bufsize = bufsize;
- fp->wp = fp->rp = fp->buf;
- fp->cnt = 0;
- fp->hiwat = 0;
- fp->overrun = 0;
- base = ap->addr;
- ap->trigchar = trigchar;
-
- sprintf (termname, "/%s%d", prefix, base);
- if ((ap->vec = (unsigned) fopen(termname, "a+")) == 0) {
- tprintf("asy%d: Open failed.\n", dev);
- return -1;
- }
- setbuf ((FILE *) ap->vec, NULL);
- asy_speed(dev,speed);
-
- _gs_opt(fileno((FILE *)ap->vec), &sbuf);
- sbuf.sg_case = 0;
- sbuf.sg_backsp = 0;
- sbuf.sg_delete = 0;
- sbuf.sg_echo = 0;
- sbuf.sg_alf = 0;
- /* sbuf.sg_nulls = 0; */
- sbuf.sg_pause = 0;
- sbuf.sg_page = 0;
- sbuf.sg_bspch = 0;
- sbuf.sg_dlnch = 0;
- sbuf.sg_eorch = 0;
- sbuf.sg_eofch = 0;
- sbuf.sg_rlnch = 0;
- sbuf.sg_dulnch = 0;
- sbuf.sg_psch = 0;
- sbuf.sg_kbich = 0;
- sbuf.sg_kbach = 0;
- sbuf.sg_bsech = 0;
- sbuf.sg_bellch = 0;
- sbuf.sg_xon = 0;
- sbuf.sg_xoff = 0;
- /* sbuf.sg_tabcr = 0;
- sbuf.sg_tabsiz = 0; */
- _ss_opt(fileno((FILE *)ap->vec), &sbuf);
-
- ifp->txproc = newproc( ifn = if_name(ifp," tx"),
- 256, asy_tx, dev, ifp, NULL, 0);
- free(ifn);
-
- return 0;
- }
-
-
- int
- asy_stop(ifp)
- struct iface *ifp;
- {
- register unsigned base;
- register struct asy *ap;
-
- ap = &Asy[ifp->dev];
- free(ap->fifo.buf);
- fclose ((FILE *)ap->vec);
- ap->vec = 0;
- return 0;
- }
-
-
- /* Asynchronous line I/O control */
- int32
- asy_ioctl(ifp,cmd,set,val)
- struct iface *ifp;
- int cmd;
- int set;
- int32 val;
- {
- struct asy *ap = &Asy[ifp->dev];
- int16 base = ap->addr;
-
- switch(cmd){
- case PARAM_SPEED:
- if(set)
- asy_speed(ifp->dev,val);
- return ap->speed;
- #ifdef notyet
- case PARAM_DTR:
- if(set) {
- writebit(base+MCR,MCR_DTR,(int)val);
- ap->dtr_usage = (val) ? MOVED_UP : MOVED_DOWN;
- }
- return (inportb(base+MCR) & MCR_DTR) ? TRUE : FALSE;
- case PARAM_RTS:
- if(set) {
- writebit(base+MCR,MCR_RTS,(int)val);
- ap->rts_usage = (val) ? MOVED_UP : MOVED_DOWN;
- }
- return (inportb(base+MCR) & MCR_RTS) ? TRUE : FALSE;
- case PARAM_DOWN:
- clrbit(base+IER,(char)IER_DAV);
- clrbit(base+MCR,MCR_RTS);
- clrbit(base+MCR,MCR_DTR);
- ap->rts_usage = MOVED_DOWN;
- ap->dtr_usage = MOVED_DOWN;
- return FALSE;
- case PARAM_UP:
- setbit(base+IER,(char)IER_DAV);
- setbit(base+MCR,MCR_RTS);
- setbit(base+MCR,MCR_DTR);
- ap->rts_usage = MOVED_UP;
- ap->dtr_usage = MOVED_UP;
- return TRUE;
- case PARAM_BLIND:
- setbit(base+IER,(char)IER_DAV);
- ap->rlsd_line_control = IGNORED;
-
- if ( ap->monitor != NULL ) {
- killproc( ap->monitor );
- ap->monitor = NULL;
- }
-
- /* can't see what we are doing, so pretend we're up */
- if ( ifp->iostatus != NULL ) {
- (*ifp->iostatus)(ifp, PARAM_UP, 0L);
- }
- return TRUE;
- #endif
- };
- return -1;
- }
-
-
- /* Set asynch line speed */
- int
- asy_speed(dev,speed)
- int dev;
- long speed;
- {
- return 0;
- }
-
-
- /* Start transmission of a buffer on the serial transmitter */
- static void
- asy_output(dev,buf,cnt)
- int dev;
- char *buf;
- unsigned short cnt;
- {
- struct asy *asyp;
-
- if(dev < 0 || dev >= ASY_MAX)
- return;
- asyp = &Asy[dev];
- if(asyp->iface == NULLIF)
- return;
- asyp->txints++;
- asyp->txchar += cnt;
- fwrite (buf, 1, cnt, (FILE *)asyp->vec);
- }
-
-
- /* Blocking read from asynch line
- * Returns character or -1 if aborting
- * Returns -2 (CD_DOWN) if carrier checking is on and dropped
- */
- int
- get_asy(dev)
- int dev;
- {
- char i_state;
- register struct fifo *fp;
- char c;
-
- fp = &Asy[dev].fifo;
-
- while(fp->cnt == 0){
- if(kwait(fp) != 0)
- return -1;
- }
- fp->cnt--;
-
- c = *fp->rp++;
- if(fp->rp >= &fp->buf[fp->bufsize])
- fp->rp = fp->buf;
-
- return uchar(c);
- }
-
- /* Process received characters */
- static int
- asyrxint(asyp)
- struct asy *asyp;
- {
- register struct fifo *fp;
- char c,lsr;
- int cnt = 0, doneone = 0;
- int trigseen = FALSE;
-
- if (!asyp->vec)
- return cnt;
- fp = &asyp->fifo;
- for(;;){
- if(_gs_rdy(fileno((FILE *)asyp->vec)) > 0){
- asyp->rxchar++;
- doneone = 1;
- fread (&c, 1, 1, (FILE *)asyp->vec);
- if(asyp->trigchar == uchar(c))
- trigseen = TRUE;
- /* If buffer is full, we have no choice but
- * to drop the character
- */
- if(fp->cnt != fp->bufsize){
- *fp->wp++ = c;
- if(fp->wp >= &fp->buf[fp->bufsize])
- /* Wrap around */
- fp->wp = fp->buf;
- fp->cnt++;
- if(fp->cnt > fp->hiwat)
- fp->hiwat = fp->cnt;
- cnt++;
- } else
- fp->overrun++;
- } else
- break;
- }
- if(cnt > asyp->rxhiwat)
- asyp->rxhiwat = cnt;
- if(trigseen)
- ksignal(fp,1);
- if (doneone)
- asyp->rxints++;
- return cnt;
- }
-
-
- /* Poll the asynch input queues; called on every clock tick.
- * This helps limit the interrupt ring buffer occupancy when long
- * packets are being received.
- */
- void
- asytimer()
- {
- register struct asy *asyp;
- register struct fifo *fp;
- register int i;
-
- for(i=0;i<ASY_MAX;i++){
- asyp = &Asy[i];
- asyrxint (asyp);
- fp = &asyp->fifo;
- if(fp->cnt != 0)
- ksignal(fp,1);
- #ifdef notyet TIPMAIL
- if (Tipsuspended[i].ifp) {
- if (!carrier_detect(i)) {
- char buf[40];
- sprintf (buf, "start tip %s %s %d\n", Tipsuspended[i].ifp->name, (Tipsuspended[i].modem) ? "m" : "t", Tipsuspended[i].timeout);
- cmdparse(Cmds,buf,NULL);
- Tipsuspended[i].ifp = 0;
- Tipsuspended[i].modem = 0;
- Tipsuspended[i].timeout = 0;
- }
- }
- #endif
- }
- }
-
-
- int
- doasystat(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct asy *asyp;
-
- for(asyp = Asy;asyp < &Asy[ASY_MAX];asyp++){
- if(asyp->iface == NULLIF)
- continue;
-
- tprintf("%s:",asyp->iface->name);
- if(asyp->trigchar != -1)
- tprintf(" [trigger 0x%02x]",asyp->trigchar);
- #ifdef notyet
- switch (asyp->cts_flow_control) {
- case MOVED_DOWN:
- case MOVED_UP:
- tprintf(" [cts flow control]");
- break;
- };
- switch (asyp->rlsd_line_control) {
- case MOVED_DOWN:
- case MOVED_UP:
- tprintf(" [rlsd line control]");
- break;
- case IGNORED:
- tprintf(" [blind]");
- break;
- };
- #endif
- tprintf(" %lu bps\n",asyp->speed);
-
- tprintf(" RX: %lu int, %lu chr, %lu hw over, %lu hw hi\n",
- asyp->rxints,
- asyp->rxchar,
- asyp->overrun,
- asyp->rxhiwat);
- asyp->rxhiwat = 0;
- if(tprintf(" TX: %lu int, %lu chars, %u q\n",
- asyp->txints, asyp->txchar, len_q(asyp->sndq)) == EOF)
- break;
- }
- return 0;
- }
-
-
- /* Send a message on the specified serial line */
- int
- asy_send(dev,bp)
- int dev;
- struct mbuf *bp;
- {
- if(dev < 0 || dev >= ASY_MAX)
- return -1;
- enqueue(&Asy[dev].sndq,bp);
- return 0;
- }
-
-
-
- /* Serial transmit process, common to all protocols */
- static void
- asy_tx(dev,p1,p2)
- int dev;
- void *p1;
- void *p2;
- {
- register struct mbuf *bp;
- struct asy *asyp;
-
- asyp = &Asy[dev];
-
- for(;;){
- /* Fetch a buffer for transmission */
- while(asyp->sndq == NULLBUF)
- kwait(&asyp->sndq);
-
- bp = dequeue(&asyp->sndq);
-
- while(bp != NULLBUF){
- /* Start the transmitter */
- asy_output(dev,bp->data,bp->cnt);
-
- /* Now do next buffer on chain */
- bp = free_mbuf(bp);
- }
- }
- }
-
-
- int
- carrier_detect(dev)
- int dev;
- {
- return 1;
- }
-
-
-
- #endif /* OSK */
-
-